#include "authmanager.h"
#include <QStandardItem>
#include <QListView>
#include <QComboBox>
#include <QWidget>
#include <QMap>

enum PermissionFlag : int
{
    None = 0,
    ViewExpdata      = (1 << 0), // 数据管理
    ViewStartExp     = (1 << 1), // 开始实验
    ViewSetParameter = (1 << 2), // 参数设置
    ViewPerformance  = (1 << 3), // 性能确认
    ViewSystemLog    = (1 << 4), // 系统日志
    ViewCommLog      = (1 << 5), // 通信日志
    ViewSetPassword  = (1 << 6), // 密码设置
    ViewSetNetwork   = (1 << 7), // 网络设置
    ViewSetLanguage  = (1 << 8), // 语言设置
    ViewPrint        = (1 << 9), // 打印设置
    ViewSetTime      = (1 << 10),// 时间设置
    ViewUserManage   = (1 << 11),// 用户管理
    ViewAbout        = (1 << 12),// 关于本机
    ViewSysUpdate    = (1 << 13),// 软件升级
    ViewFactory      = (1 << 14),// 厂家设置
    ViewAllData      = (1 << 15),// 实验数据
    PermissionMask   = 0x0000ffff,
};

// 控件id
static const QMap<PermissionFlag, QString> controlAuthMap = {
    { ViewExpdata,      "btnData" },
    { ViewStartExp,     "btnExp" },
    { ViewSetParameter, "btnParamSet" },
    { ViewPerformance,  "btnPerformance" },
    { ViewSystemLog,    "btnLog" },
    { ViewCommLog,      "cbxLogType#CommunicationLog" },
    { ViewSetPassword,  "btnPassword" },
    { ViewSetNetwork,   "btnNetwork" },
    { ViewSetLanguage,  "btnLanguage" },
    { ViewPrint,        "btnPrint" },
    { ViewSetTime,      "btnTime" },
    { ViewUserManage,   "btnUserManage" },
    { ViewAbout,        "btnAbout" },
    { ViewSysUpdate,    "btnSysUpdate" },
    { ViewFactory,      "btnFactory" },
};

// ui权限定义表
static const QMap<int, PermissionFlag> uiAuthMap = {
    { SetParameter, ViewSetParameter },
    { Performance,  ViewPerformance },
    { SystemLog,    ViewSystemLog },
    { SetNetwork,   ViewSetNetwork },
    { SetLanguage,  ViewSetLanguage },
    { Print,        ViewPrint },
    { SetTime,      ViewSetTime },
    { SysUpdate,    ViewSysUpdate },
    { Experiment,   ViewStartExp },
    { AllData,      ViewAllData },
};

struct UserPrivate {
    int basePermission;
    bool preset;
};

static const QString MANUFACTURER = "service";
static const QString ADMINISTRATOR = "admin";
static const QString DEFAULTROLE = "user";

// 默认角色权限
static const QMap<QString, UserPrivate> baseAuthMap = {
    { MANUFACTURER, { 65471, true } },
    { ADMINISTRATOR, { 49119, true } },
    { DEFAULTROLE, { 4163, false } },
};

AuthManager::AuthManager()
{
}

AuthManager *AuthManager::instance()
{
    static AuthManager am;
    return &am;
}

static void findChildren(const QWidget *form, QMultiMap<QString, QWidget *> &map)
{
    QWidgetList objectList = form->findChildren<QWidget *>();
    foreach (QWidget *obj, objectList)
    {
        map.insert(obj->objectName(), obj);
        findChildren(obj, map);
    }
}

static void showComboBoxItems(QWidget *obj, const QString &itemName, bool visiable)
{
    QComboBox *combobox = qobject_cast<QComboBox *>(obj);
    QListView *view = qobject_cast<QListView *>(combobox->view());
    QStandardItemModel *model = qobject_cast<QStandardItemModel *>(combobox->model());

    if (view)
    {
        int itemIndex = -1;
        for (int i = 0; i < combobox->count(); ++i)
        {// 查找item项
            if (combobox->itemData(i).toString() == itemName)
            {
                itemIndex = i;
                break;
            }
        }

        if (itemIndex == -1)
        {
            return;
        }

        combobox->blockSignals(true);
        QStandardItem *item = model->item(itemIndex);

        if (visiable)
        {
            view->setRowHidden(itemIndex, false);
            if (item)
            {
                item->setFlags(item->flags() | Qt::ItemIsEnabled);
            }
        }
        else
        {
            view->setRowHidden(itemIndex, true);
            if (item)
            {
                item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
            }
        }

        bool hasVisibleItem = false;
        for (int i = 0; i < combobox->count(); ++i)
        {// 查找可见item
            if (!view->isRowHidden(i))
            {
                hasVisibleItem = true;
                break;
            }
        }

        combobox->setCurrentIndex(hasVisibleItem ? 0 : -1);
        combobox->blockSignals(false);
    }
}

void AuthManager::showControls(QWidget *form, int permission)
{
    QMultiMap<QString, QWidget *> map;
    findChildren(form, map);

    int authCode = permission & PermissionMask;
    foreach (const PermissionFlag &flag, controlAuthMap.keys())
    {
        const QString &objectName = controlAuthMap[flag];

        if (objectName.contains("#"))
        {
            bool visiable = ((authCode & flag) == flag);
            QList<QString> names = objectName.split("#");
            if (names.length() > 1)
            {// 遍历item
                foreach (QWidget *obj, map.values(names[0]))
                {
                    if (obj->inherits("QComboBox"))
                    {
                        showComboBoxItems(obj, names[1], visiable);
                    }
                }
            }

            continue;
        }

        bool visiable = ((authCode & flag) == flag) && map.contains(objectName);
        foreach (QWidget *obj, map.values(objectName))
        {
            if (visiable)
            {
                obj->setVisible(true);
            }
            else
            {
                obj->setHidden(true);
            }
        }
    }
}

int AuthManager::showContainer(QWidget *form)
{
    QList<QWidget *> items = form->findChildren<QWidget *>();

    int visibleCount = 0;
    int firstVisibleIndex = -1;

    for (int i = 0; i < items.count(); ++i)
    {// 查找父容器要显示的第一个item
        if (!items[i]->isHidden())
        {
            ++visibleCount;
            firstVisibleIndex = (firstVisibleIndex != -1) ? firstVisibleIndex : i;
        }
    }

    // 父容器至少有两个item显示父容器，否则隐藏
    form->setVisible(visibleCount > 1);

    if (firstVisibleIndex != -1)
    {// 切换到第一个显示的item
        items[firstVisibleIndex]->setVisible(true);
    }

    return firstVisibleIndex;
}

bool AuthManager::hasPermission(int permission, RolePermissionIndex index)
{
    int authCode = permission & PermissionMask;
    PermissionFlag f = uiAuthMap.contains(index) ? uiAuthMap[index] : None;
    return (authCode & f) != 0;
}

int AuthManager::addPermission(int permission, RolePermissionIndex index)
{
    int authCode = permission & PermissionMask;
    PermissionFlag f = uiAuthMap.contains(index) ? uiAuthMap[index] : None;
    return authCode | f;
}

int AuthManager::removePermission(int permission, RolePermissionIndex index)
{
    int authCode = permission & PermissionMask;
    PermissionFlag f = uiAuthMap.contains(index) ? uiAuthMap[index] : None;
    return authCode & ~f;
}

int AuthManager::basePermission(const QString &roleName)
{
    const QString role = baseAuthMap.contains(roleName) ? roleName : "user";
    return baseAuthMap[role].basePermission;
}

bool AuthManager::isPresetAccount(const QString &name)
{
    const QString role = baseAuthMap.contains(name) ? name : "user";
    return baseAuthMap[role].preset;
}

bool AuthManager::isManufacturer(const QString &name)
{
    return name == MANUFACTURER;
}

bool AuthManager::isAdministrator(const QString &name)
{
    return name == ADMINISTRATOR;
}

QString AuthManager::manufacturer()
{
    return MANUFACTURER;
}
